package com.mycompany.project.client.chee;

import java.util.ArrayList;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DoubleClickEvent;
import com.google.gwt.event.dom.client.DoubleClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.ToggleButton;
import com.allen_sauer.gwt.dnd.client.PickupDragController;
import com.allen_sauer.gwt.dnd.client.drop.AbsolutePositionDropController;
import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.widget.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.mycompany.project.client.neville.QualityCheckGUI;

/**
 * This class displays the calculated habitat configurations
 * @author LeeNou
 *
 */
@SuppressWarnings("deprecation")
public class ConfigurationGUI {
	//This is the set maximum configuration to be displayed.
	public static final int MAX_CONFIG = 2;
	//this is the scroll panel that will hold the grid of the habitat configuration.
	private static ScrollPanel []sHab = new ScrollPanel[MAX_CONFIG];
	//this is the grid that will display the configuration.
	private static Grid []gHab = new Grid[MAX_CONFIG];
	private static VerticalPanel []vHab = new VerticalPanel[MAX_CONFIG];
	private static Button []tBtnHab = new Button[MAX_CONFIG];
	private static Button []tBtnHabMax = new Button[MAX_CONFIG];
	private static Button[] placeHabitBtn = new Button[MAX_CONFIG];
	private static HTML []confLabel = new HTML[MAX_CONFIG];
	private static HabitatConfiguration []hConfiguration = new HabitatConfiguration[MAX_CONFIG];
	public static final int ROW = 16;
	public static final int COL = 16;
	private  static Grid configMap = new Grid(MapGUI.ROW,MapGUI.COL);
	private static ArrayList<ArrayList<Module>> configMapList = new ArrayList<ArrayList<Module>>();
	private static boolean []canPlace = new boolean[MAX_CONFIG];
	//drag and drop
	private static PickupDragController []dragController = new PickupDragController[MAX_CONFIG];
	private static AbsolutePanel[][][] target = new AbsolutePanel[MAX_CONFIG][ROW][COL];
	private static AbsolutePositionDropController [][][]boundary = new AbsolutePositionDropController[MAX_CONFIG][ROW][COL];
	
	public ConfigurationGUI()
	{
		initMap();
		initConfig();
	}
	public static Grid getConfigMap()
	{
		return configMap;
	}
	public ScrollPanel getScroll(int k)
	{
		return sHab[k];
	}
	public Grid getGrid(int k)
	{
		return gHab[k];
	}
	private static void checkAndUpdate(Module temp,int k,int row, int col)
	{
		int j = temp.getModuleType().ordinal();
		for(int i=0; i< hConfiguration[k].getGridList().get(j).size();i++)
		{
			Module gModule = hConfiguration[k].getGridList().get(j).get(i);
			if(temp.getCodeNumber() == gModule.getCodeNumber())
			{
				//remove this module from the grid
				int row1 = gModule.getGridY();
				int col1 = gModule.getGridX();
				if(hConfiguration[k].getmGrid()[row1][col1] != null && hConfiguration[k].getmGrid()[row1][col1].equals(temp))
					hConfiguration[k].getmGrid()[row1][col1] = null; // set this to null
				//once we found this module in the list, we'll update its grid coordinates
				hConfiguration[k].getGridList().get(j).get(i).setGridX(col);
				hConfiguration[k].getGridList().get(j).get(i).setGridY(row);
				hConfiguration[k].getGridList().get(j).get(i).setTitle
				(hConfiguration[k].getGridList().get(j).get(i).getString());
				//update this module on the grid
				//update the grid 
				if(hConfiguration[k].getmGrid()[row1][col1]==null)
					hConfiguration[k].getmGrid()[row][col] = temp;
				//exit once finished
				i = hConfiguration[k].getGridList().get(j).size();
			}
		}
	}
	public static HabitatConfiguration getHConfiguration(int k)
	{
		return hConfiguration[k];
	}
	/**
	 * This method will update the grid list correctly according to the configuration map
	 */
	public static void updateGridList(int k)
	{
		for (int i = 1 ; i < ROW ; i++)
		{
			for (int j = 1; j < COL; j++)
			{
				
				if(target[k][i][j].getWidgetCount() == 1)
				{
					Module temp = (Module)target[k][i][j].getWidget(0);
					checkAndUpdate(temp,k,i,j);
				}
				else if(target[k][i][j].getWidgetCount() > 1)
				{
					Window.alert("Cell("+i+","+j+") contains more than 1 module. Nothing is updated!");
					return;
				}
			}
		}
	}
	public void setGrid(int k,Module m)
	{
		
		//Image img = new Image(Module.getModuleImage(m.getModuleType().ordinal()));
		m.setUrl(Module.getModuleImage(m.getModuleType().ordinal()));
		m.setTitle(m.getString());
		//img.setTitle(m.getString());
		target[k][m.getGridY()][m.getGridX()].add(m);
		dragController[k].makeDraggable(m);
	}
	public VerticalPanel getGUI(int i)
	{
		return vHab[i];
	}
	public static void setHabConfigBtn(boolean isOn)
	{
		for(int i=0;i<MAX_CONFIG;i++)
		{
			tBtnHab[i].setEnabled(isOn);
		}
	}
	public static void setPlaceBtn(boolean isOn)
	{
		for(int i=0;i<MAX_CONFIG;i++)
		{
			placeHabitBtn[i].setEnabled(isOn);
		}
	}
	public static void setHabConfigBtnMax(boolean isOn)
	{
		for(int i=0;i<MAX_CONFIG;i++)
		{
			tBtnHabMax[i].setEnabled(isOn);
		}
	}
	private void initConfig()
	{
		initConfigMapList();
		//initialize the configuration panels
		for( int i=0;i<MAX_CONFIG;i++)
		{
			//init
			hConfiguration[i] = new HabitatConfiguration();
			sHab[i] = new ScrollPanel();
			gHab[i] = new Grid(ROW,COL);
			gHab[i].setBorderWidth(2);
			gHab[i].setStyleName("bgMap");
			vHab[i] = new VerticalPanel();
			dragController[i] = new PickupDragController(RootPanel.get(),false);
			confLabel[i] = new HTML();
			//gHab[i].clear();
			vHab[i].setHorizontalAlign(HorizontalAlignment.CENTER);
			tBtnHab[i] = new Button("<center>Configure Min</center>");
			tBtnHabMax[i] = new Button("<center>Configure Max</center>");
			HorizontalPanel hButtonPanel = new HorizontalPanel();
			//add and set
			sHab[i].add(gHab[i]);
			vHab[i].add(new HTML("<center><b>Habitat Configuration "+i+"</b></center>"));
			vHab[i].add(sHab[i]);
			confLabel[i] = new HTML("<center>Click \"Configure\" for new configuration</center>");
			vHab[i].add(confLabel[i]);
			hButtonPanel.add(tBtnHab[i]);
			hButtonPanel.add(tBtnHabMax[i]);
			placeHabitBtn[i] = new Button("Place Habitat");
			vHab[i].add(hButtonPanel);
			vHab[i].add(placeHabitBtn[i]);
			gHab[i].setSize("327px","240px");
			sHab[i].setSize("327px","240px");
			//create grid
			redraw(i);
			
			//btn
			final int temp = i;
			tBtnHab[i].addClickListener(new ClickListener(){
				 
				@Override
				public void onClick(Widget sender) {
					if(hConfiguration[temp].buildMin(configMapList))
					{
						redraw(temp);
						for(int i=0;i<hConfiguration[temp].getGridList().size();i++)
						{
							for(int j=0; j<hConfiguration[temp].getGridList().get(i).size();j++)
							{
								Module m = hConfiguration[temp].getGridList().get(i).get(j);
								setGrid(temp, m);
							}
						}
						placeHabitBtn[temp].setEnabled(true);
						confLabel[temp].setHTML("<center>Minimum Configuration Successfully Built!</center>");
					}
					else 
					{
						placeHabitBtn[temp].setEnabled(false);
						confLabel[temp].setHTML("<center>Not enough usable modules!</center>");
					}
					
				}
				
			});
			tBtnHabMax[i].addClickListener(new ClickListener(){

				@Override
				public void onClick(Widget sender) {
					if(hConfiguration[temp].buildMax(configMapList))
					{
						redraw(temp);
						for(int i=0;i<hConfiguration[temp].getGridList().size();i++)
						{
							for(int j=0; j<hConfiguration[temp].getGridList().get(i).size();j++)
							{
								Module m = hConfiguration[temp].getGridList().get(i).get(j);
								setGrid(temp, m);
							}
						}
						placeHabitBtn[temp].setEnabled(true);
						confLabel[temp].setHTML("<center>Maximum Configuration Successfully Built!</center>");
					}
					else 
					{
						placeHabitBtn[temp].setEnabled(true);
						confLabel[temp].setHTML("<center>Not enough usable modules!</center>");
					}
					
				}
				
			});
			placeHabitBtn[i].addClickHandler(new ClickHandler(){

				@Override
				public void onClick(ClickEvent event) {
					//play config accepted sound
					MHCSound.playConfigAccepted();
					for(int a=0;a<MAX_CONFIG;a++)
					{
						if(a == temp) canPlace[temp] = true;
						else canPlace[a] = false;
					}
					updateGridList(temp);
					Window.alert("Habitat configuration "+temp+" is now selected, please click on the Map tab " +
							"and, at the bottom, switch to the configuration map. Then choose the best fit " +
							"spot to place the new habitat.");
					for(int i=1;i<MapGUI.ROW;i++)
					{
						for(int j=1;j<MapGUI.COL;j++)
						{
							if(configMap.getWidget(i, j) != null)
							{
								Module t = (Module)configMap.getWidget(i, j);
								for(int m=0;m<hConfiguration[temp].getGridList().get(t.getModuleType().ordinal()).size();m++)
								{
									if(t.getCodeNumber() == hConfiguration[temp].getGridList().get(t.getModuleType().ordinal()).get(m).getCodeNumber())
									{
										configMap.remove(t);
									}
								}
							}
						}
					}
				}
				
			});
		}
		setPlaceBtn(false);
		setHabConfigBtn(false);
		setHabConfigBtnMax(false);
		//This will place the module habitat on the configuration map according to the cell selected
        configMap.addDoubleClickHandler(new DoubleClickHandler(){

			@Override
			public void onDoubleClick(DoubleClickEvent event) {
				int row = ((event.getRelativeY(event.getRelativeElement())/22));
				int col = ((event.getRelativeX(event.getRelativeElement())/18));
				int k = 0;
				if(canPlace[1] == true){
					k = 1;
				}
				else if(canPlace[0] == true) k = 0;
				else return;
				if(row == Rover.getRoverRow() && col == Rover.getRoverCol())
				{
					Window.alert("Can not place at same spot as rover");
					return;
				}
				Window.alert("You have selected ROW "+row+" COL "+col);
				placeModule(k,row,col);
				final DialogBox popUp = new DialogBox(false);
	      		final VerticalPanel popPanel = new VerticalPanel();
	      		final HorizontalPanel hPanel = new HorizontalPanel();
	      		final ToggleButton noBtn = new ToggleButton("no");
	      		noBtn.setWidth("50px");
	      		final ToggleButton yesBtn = new ToggleButton("yes");
	      		yesBtn.setWidth("50px");
	      		popPanel.add(new HTML("<center>Done placing habitat?</center>"));
	      		popPanel.add(hPanel);
	      		popUp.setWidget(popPanel);
	      		hPanel.add(yesBtn);
	      		hPanel.add(noBtn);
	      		popPanel.setHorizontalAlign(HorizontalAlignment.CENTER);
	      		hPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
	      		popUp.setPopupPosition(400, 100);
	      	    popUp.show();
	      	  yesBtn.addClickListener(new ClickListener(){

				@Override
				public void onClick(Widget sender) {
					yesBtn.setDown(false);
					for(int i = 0; i < MAX_CONFIG; i++)
					{
						redraw(i);
						canPlace[i] = false;
						placeHabitBtn[i].setEnabled(false);
						if( hConfiguration[i].getGridList() != null) {
							for (int l = 0; l < hConfiguration[i].getGridList().size(); l++) {
								hConfiguration[i].getGridList().get(l).clear();
							}
						}
					}
					//play habitat created sound
					MHCSound.playHabitatCreated();
					QualityCheckGUI.getTextA().clear();
					QualityCheckGUI.getTextB().clear();
        	    	  popUp.hide();
				}
	      	  });
	       		noBtn.addClickHandler(new ClickHandler() {
	       	        public void onClick(ClickEvent event) {
	       	        	if (noBtn.isDown()) {
	               			popUp.hide();
	               			noBtn.setDown(false);
	       	        	}
	       	        } });
			}
			
		});
	}
	public static void redraw(int i)
	{
		dragController[i].unregisterDropControllers();
		gHab[i].clear();
		for(int k=0; k<ROW;k++)
		{
			gHab[i].setWidget(k, 0, new HTML("<font color=\"white\"><center>"+k+"</center></font>"));
		  }
	   for(int j = 0; j<COL; j++)
	   {
		   if(j<10) gHab[i].setWidget(0, j, new HTML("<font color=\"white\"><center>_"+j+"</center></font>"));
		   else gHab[i].setWidget(0, j, new HTML("<font color=\"white\"><center>"+j+"</center></font>"));
		  }
	   //drag and drop
	   for(int k=1; k<ROW;k++)
		{
		   for(int j = 1; j<COL; j++)
		   {
			   if(target[i][k][j] == null )target[i][k][j] = new AbsolutePanel();
			   else target[i][k][j].clear();
			   if(boundary[i][k][j] == null) boundary[i][k][j] = new AbsolutePositionDropController(target[i][k][j]);
			   target[i][k][j].setSize("13px","13px");
			   gHab[i].setWidget(k, j,target[i][k][j]);
			   dragController[i].registerDropController(boundary[i][k][j]);
		   }
		}
	   confLabel[i].setHTML("<center>Click \"Configure\" for new configuration</center>");
	}
	private static void initConfigMapList()
	{
		for(int i=0; i< Module.MAX_SIZE;i++)
		{
			configMapList.add(new ArrayList<Module>());
		}
	}
	private static void checkConfigMapList(int k)
	{
		for(int b=0;b<hConfiguration[k].getGridList().size();b++)
		{
			for(int c=0;c<hConfiguration[k].getGridList().get(b).size();c++)
			{
				for(int j=0;j<configMapList.get(b).size();j++)
				{
					if(hConfiguration[k].getGridList().get(b).get(c).getCodeNumber() ==
							configMapList.get(b).get(j).getCodeNumber()	)
					{
						configMap.remove(configMapList.get(b).get(j));
						configMapList.get(b).remove(j);
					}
					
				}
			}
		}
	}
	
	public static void showAllChanges()
	{
		initMap();
		int count = 0;
		for(int i=1;i<MapGUI.ROW;i++)
		{
			for(int j=1;j<MapGUI.COL;j++)
			{
				if(MapGUI.getGrid().getWidget(i, j) != null)
				{
					Module tmp = (Module)MapGUI.getGrid().getWidget(i, j);
					Module temp = new Module();
					temp.setUrl(tmp.getUrl());
					temp.setCodeNumber(tmp.getCodeNumber());
					temp.setStats(tmp.getStats());
					temp.setOrientation(tmp.getOrientation());
					temp.setPositionX(tmp.getPositionX());
					temp.setPositionY(tmp.getPositionY());
					temp.setModuleType(tmp.getModuleType());
					temp.setTitle(tmp.getString());
					count = 0;
					if(!configMapList.get(tmp.getModuleType().ordinal()).isEmpty())
					{
						for(int m=0;m<configMapList.get(tmp.getModuleType().ordinal()).size();m++)
						{
							if(tmp.getCodeNumber() != configMapList.get(tmp.getModuleType().ordinal()).get(m).getCodeNumber())
							{
								count++;
							}
							if(count == configMapList.get(tmp.getModuleType().ordinal()).size())
							{
								configMap.setWidget(i, j, temp);
							}
						}
					}
					else 
					{
						configMap.setWidget(i, j, temp);
					}
				}
			}
		}
		displayOnlyHabitat();
		for(int a=0;a<MAX_CONFIG;a++)
		{
			if(canPlace[a])
			{
				for(int i=1;i<MapGUI.ROW;i++)
				{
					for(int j=1;j<MapGUI.COL;j++)
					{
						if(configMap.getWidget(i, j) != null)
						{
							Module t = (Module)configMap.getWidget(i, j);
							for(int m=0;m<hConfiguration[a].getGridList().get(t.getModuleType().ordinal()).size();m++)
							{
								if(t.getCodeNumber() == hConfiguration[a].getGridList().get(t.getModuleType().ordinal()).get(m).getCodeNumber())
								{
									configMap.remove(t);
								}
							}
						}
					}
				}
			}
		}
	}
	public static void displayOnlyHabitat()
	{
		for(int i = 0; i < configMapList.size();i++)
		{
			for(int j = 0; j < configMapList.get(i).size(); j++)
			{
				Module tmp = configMapList.get(i).get(j);
				configMap.setWidget(tmp.getGridY(), tmp.getGridX(), tmp);
			}
		}
	}
	private static void placeModule(int k,int startRow,int startCol)
	{
		updateGridList(k);
		if(canPlace[0]==false && canPlace[1]==false)
		{
			Window.alert("No habitat configuration selected!");
			return;
		}
		checkConfigMapList(k);
		//calculate where to place the modules correctly
		for(int i=0;i<hConfiguration[k].getGridList().size();i++)
		{
			for(int j=0; j<hConfiguration[k].getGridList().get(i).size();j++)
			{
				int currentRow = hConfiguration[k].getGridList().get(i).get(j).getGridY();
				int shiftRow = currentRow  -   hConfiguration[k].getGridList().get(0).get(0).getGridY();
				int currentCol = hConfiguration[k].getGridList().get(i).get(j).getGridX();
				int shiftCol = currentCol -  hConfiguration[k].getGridList().get(0).get(0).getGridX();
				Module m = new Module();
				//new module to the configuration map
				m.setUrl(hConfiguration[k].getGridList().get(i).get(j).getUrl());
				m.setCodeNumber(hConfiguration[k].getGridList().get(i).get(j).getCodeNumber());
				m.setModuleType(hConfiguration[k].getGridList().get(i).get(j).getModuleType());
				m.setStats(hConfiguration[k].getGridList().get(i).get(j).getStats());
				m.setOrientation(hConfiguration[k].getGridList().get(i).get(j).getOrientation());
				m.setGridX(startCol+shiftCol);
				m.setGridY(startRow+shiftRow);
				m.setPositionX(hConfiguration[k].getGridList().get(i).get(j).getPositionX());
				m.setPositionY(hConfiguration[k].getGridList().get(i).get(j).getPositionY());
				m.setTitle(m.getString());
				//remove m if it's already on the list or add/update new module
				if(!configMapList.get(i).isEmpty()) configMapList.get(i).remove(m);
				configMapList.get(i).add(m);
				
				if((startRow+shiftRow)<MapGUI.ROW && (startCol+shiftCol) < MapGUI.COL && 
						(startCol+shiftCol)  > 0 && (startRow+shiftRow) > 0 && 
						configMap.getWidget((startRow+shiftRow),(startCol+shiftCol)) == null)
				{
					configMap.setWidget((startRow+shiftRow),(startCol+shiftCol),m);
				}
				else 
				{
					Window.alert("Can't place module, it is out of range");
				}
			}
		}
	}
	 public static void initMap() {
		    configMap.clear();
		    configMap.setBorderWidth(2);
		    configMap.setCellPadding(4);
		    configMap.setStyleName("bgMap");
	        for (int i = 0; i < MapGUI.ROW; i++) {
	        	configMap.setWidget(i, 0, new HTML("<center><font color=\"white\">"
	                    + i + "</center></font>"));
	        }
	        for (int j = 0; j < MapGUI.COL; j++) {
	            if (j < Module.MAX_SIZE) {
	            	configMap.setWidget(0, j, new HTML(
	                        "<font color=\"white\"><center>_" + j
	                                + "</center></font>"));
	            } else {
	            	configMap.setWidget(0, j, new HTML(
	                        "<font color=\"white\"><center>" + j
	                                + "</center></font>"));
	            }
	        }
	 }
	 public static void clearConfigMapList()
	 {
		 for(int i=0;i<configMapList.size();i++)
		 {
			 configMapList.get(i).clear();
		 }
	 }
	 
}
